#include <stdio.h>
#include <string.h>
#include "3d_model.h"

D3ModelPart::D3ModelPart(float *xyz, D3ModelPartType type, uint32_t color, Film *film)
{
    this->type = type;
    this->color = color;
    this->film = film;
    switch (type)
    {
    case D3MODEL_PART_TYPE_LINE:
        xyzNum = 2;
        memcpy(this->xyz, xyz, sizeof(float) * 3 * 2);
        break;
    case D3MODEL_PART_TYPE_TRIANGLE:
        xyzNum = 3;
        memcpy(this->xyz, xyz, sizeof(float) * 3 * 3);
        break;
    case D3MODEL_PART_TYPE_RECT:
        xyzNum = 4;
        memcpy(this->xyz, xyz, sizeof(float) * 3 * 4);
        break;
    default:
        return;
    }
};

void D3ModelPart::Print()
{
    int32_t i;
    printf("Part: type/%d num/%d WHT/%d,%d,%d ", type, xyzNum, width, height, thickness);
    for (i = 0; i < xyzNum * 3; i++)
        printf("%.1f ", xyz[i]);
    printf("\r\n");
};


D3Model::D3Model()
{
    partsList = new CrossList(NULL);
}

D3Model::~D3Model()
{
    partsList->Lock();
    CrossList *node = partsList->FirstChild();
    while (node)
    {
        if (node->value)
        {
            delete (D3ModelPart*)node->value;
            node->value = NULL;
        }
        node = node->Next();
    }
    partsList->UnLock();
    delete partsList;
}

//模型顶点构建,返回index
int32_t D3Model::AddLine(float xyz[6], uint32_t color)
{
    return partsList->PushBackChild(
        new CrossList(new D3ModelPart(xyz, D3MODEL_PART_TYPE_LINE, color)));
}

int32_t D3Model::AddLine(float x1, float y1, float z1,
            float x2, float y2, float z2,
            uint32_t color)
{
    float xyz[] = {x1, y1, z1, x2, y2, z2};
    return AddLine(xyz, color);
}

int32_t D3Model::AddTriangle(float xyz[9], uint32_t color)
{
    return partsList->PushBackChild(
        new CrossList(new D3ModelPart(xyz, D3MODEL_PART_TYPE_TRIANGLE, color)));
}

int32_t D3Model::AddTriangle(float x1, float y1, float z1,
                float x2, float y2, float z2,
                float x3, float y3, float z3,
                uint32_t color)
{
    float xyz[] = {x1, y1, z1, x2, y2, z2, x3, y3, z3};
    return AddTriangle(xyz, color);
}

int32_t D3Model::AddRect(float xyz[12], uint32_t color, Film *film)
{
    return partsList->PushBackChild(
        new CrossList(new D3ModelPart(xyz, D3MODEL_PART_TYPE_RECT, color, film)));
}

int32_t D3Model::AddRect(float x1, float y1, float z1,
            float x2, float y2, float z2,
            float x3, float y3, float z3,
            float x4, float y4, float z4,
            uint32_t color, Film *film)
{
    float xyz[] = {x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4};
    return AddRect(xyz, color, film);
}

//返回指定序号的部件
D3ModelPart* D3Model::PartAt(int32_t index)
{
    CrossList *node = partsList->ChildAt(index);
    if (!node)
        return NULL;
    return (D3ModelPart*)node->value;
}

int32_t D3Model::PartNum()
{
    return partsList->Child();
}

int32_t D3Model::SetPartColor(int32_t index, uint32_t color)
{
    D3ModelPart *part = PartAt(index);
    if (!part)
        return -1;
    part->color = color;
    return 0;
}

int32_t D3Model::SetPartFilm(int32_t index, Film *film)
{
    D3ModelPart *part = PartAt(index);
    if (!part)
        return -1;
    part->film = film;
    return 0;
}

//整体缩放,取值范围: 0.0 ~ 缩放区间 ~ 1.0 ~ 放大区间 ~ XXX
void D3Model::Zoom(float multiple)
{
    if (multiple < 0)
        multiple = -multiple;
    partsList->Lock();
    CrossList *node = partsList->FirstChild();
    while (node)
    {
        D3ModelPart *part = (D3ModelPart*)node->value;
        for (int32_t j = 0; j < part->xyzNum; j++)
            part->xyz[j] *= multiple;
        node = node->Next();
    }
    partsList->UnLock();
}
